﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Globalization;

using BMS.Models;
using BMS.Utilities;

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace BMS.Models.BusinessLogic
{
    public class QuotationDocument
    {
        private String TemplatePath = Configuration.QuotationTemplatePath;

        public void GenerateQuotation(QuotationModel quotModel, List<QuotationItemModel> quotItemList, FMModel fmModel, CompanyModel companyModel, OrderModel orderModel)
        {
            try
            {
                String destPath = Configuration.QuotationDestinationPath + quotModel.FMName + @"\";

                if (Directory.Exists(destPath) == false)
                    Directory.CreateDirectory(destPath);

                String fileName = quotModel.QuotationNo + Configuration.Underscore + DateTime.Today.ToString("yyyyMMdd") + Configuration.WordFileFormat;

                WordOpenXMLUtil.SaveAsDocx(TemplatePath, destPath, fileName);
                String destFilePath = destPath + fileName;

                using (WordprocessingDocument oDoc = WordprocessingDocument.Open(destFilePath, true))
                {
                    MainDocumentPart mainPart = oDoc.MainDocumentPart;

                    #region Quotation Item Table
                    bool IsFittedto1Page = IsLessThanOrEqualTo9Items(quotItemList);
                    int NoOfPagesRequired = (IsFittedto1Page == true) ? 1 : GetNoOfPages(quotItemList);
                    
                    Paragraph rowTable = null;
                    String tempStrn = "";

                    #region Part I - Header
                    List<HeaderPart> headerList = mainPart.HeaderParts.ToList();
                    foreach (HeaderPart header in mainPart.HeaderParts)
                    {
                        
                        Header tempHeader = header.Header;
                        SdtBlock quotHeader = header.Header.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "QuotationHeader").Single();
                        Table quotHeaderTable = quotHeader.Descendants<Table>().Single();
                        List<TableRow> RowsList = quotHeaderTable.Elements<TableRow>().ToList();
                        TableRow tempRow = RowsList[0];
                        String t = "";

                        #region 1st Row - Bill To & Quotation No
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.CompanyName)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        String tempQuotNo = quotModel.QuotationNo.Replace("Q-", "");
                        tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempQuotNo)));
                        tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        #endregion

                        #region 2nd Row - Address 1 & Work Order No
                        tempRow = RowsList[1];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address1)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(orderModel.WorkOrderNo)));
                        tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        #endregion

                        #region 3rd Row - Address 2 & Quotation Date
                        tempRow = RowsList[2];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address2)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(quotModel.QuotationCreationDate.ToString("dd-MMM-yyyy", CultureInfo.CreateSpecificCulture("en-US")))));
                        tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        #endregion

                        #region 4th Row - Address 3
                        tempRow = RowsList[3];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address3)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                        #endregion

                        #region 5th Row - Address 4 & Ref No - Service Order No
                        tempRow = RowsList[4];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address4)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(orderModel.ServiceOrderNo)));
                        tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        #endregion

                        #region 6th Row - Tel & Vendor No
                        tempRow = RowsList[5];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.TelephoneNo)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(Configuration.VendorNo)));
                        tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        #endregion

                        #region 7th Row - Fax
                        tempRow = RowsList[6];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.FaxNo)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                        #endregion

                        #region 8th Row - Attention To
                        tempRow = RowsList[7];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(fmModel.AttentionTo)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                        #endregion

                        #region 11th Row - Location - Description
                        tempRow = RowsList[10];
                        tempStrn = Configuration.ReferInShortForm + Configuration.Space + orderModel.Location + Configuration.Space + Configuration.Hyphen + Configuration.Space + orderModel.Description;

                        if (orderModel.Description == "" || orderModel.Description == null)
                            tempStrn = Configuration.ReferInShortForm + Configuration.Space + orderModel.Location;

                        tempRow.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new Bold(), new FontSize() { Val = "24" }), new Text(tempStrn)));
                        tempRow.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                        #endregion
                    }

                    #endregion

                    #region Part II - Items
                    if (IsFittedto1Page == true)
                    {
                        SdtBlock ccWithTable = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "QuotationItemTable_1").Single();
                        Table table = ccWithTable.Descendants<Table>().Single();
                        TableRow row = table.Elements<TableRow>().Last();
                        TableRow rowCopy = null;
                        
                        int currentItemNo = 1;
                        decimal TotalAmount = 0;

                        #region Part a - Items
                        foreach (QuotationItemModel item in quotItemList)
                        {
                            // Copy the blank row
                            rowCopy = (TableRow)row.Clone();
                            tempStrn = (item.ItemNo == 0) ? "" : item.ItemNo.ToString();
                            row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                            row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.ItemDescription)));
                            row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.SORItem)));
                            row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                            tempStrn = (item.Qty == 0) ? "" : item.Qty.ToString();
                            row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                            row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.Unit)));
                            row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                            tempStrn = (item.Rate == 0) ? "" : item.Rate.ToString("#,##0.00");
                            row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                            row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                            tempStrn = (item.ItemAmount == 0) ? "" : item.ItemAmount.ToString("#,##0.00");
                            TotalAmount += item.ItemAmount;
                            row.Descendants<TableCell>().ElementAt(6).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                            row.Descendants<TableCell>().ElementAt(6).Append(rowTable);

                            if (currentItemNo != quotItemList.Count)
                                table.AppendChild(rowCopy);
                            
                            row = table.Elements<TableRow>().Last();
                            currentItemNo++;
                        }
                        #endregion

                        #region Part b - last two Rows
                        table.AppendChild(rowCopy);

                        TableCellProperties tcp1 = new TableCellProperties();
                        TableCellProperties tcp2 = new TableCellProperties();

                        row = table.Elements<TableRow>().Last();
                        rowCopy = (TableRow)row.Clone();
                        table.AppendChild(rowCopy);

                        String text = "Total Amount :", text2 = TotalAmount.ToString("#,##0.00");
                        tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                            , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                        tcp2 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                            , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Double }, new TopBorder() { Val = BorderValues.Single })));

                        row = table.Elements<TableRow>().Last();
                        GridSpan gs = new GridSpan { Val = 2 };
                        row.Descendants<TableCell>().ElementAt(4).Remove();
                        row.Descendants<TableCell>().ElementAt(4).Append(gs);
                        row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                        row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                        row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        row.Descendants<TableCell>().ElementAt(5).Append(tcp2);
                        row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text2)));
                        row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                        #endregion

                        #region Part c - Remaining Lines if any
                        int NoOfRemainingLines = GetNoOfRemainingLines(quotItemList);

                        if (NoOfRemainingLines > 0)
                        {
                            for (int i = 0; i < NoOfRemainingLines; i++)
                            {
                                row = table.Elements<TableRow>().Last();
                                rowCopy = (TableRow)row.Clone();
                                table.AppendChild(rowCopy);

                                text = "";
                                tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));

                                row = table.Elements<TableRow>().Last();
                                row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                                row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                                row.Descendants<TableCell>().ElementAt(5).Append(tcp1);
                                row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        int currentTable = 1;
                        decimal TotalAmount = 0;
                        decimal BroughtForward = 0;
                        SdtBlock emptyElement = (SdtBlock)mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "QuotationItemTable_1").Single().Clone();
                        SdtBlock copyBlock = new SdtBlock();

                        for (int i = 0; i < NoOfPagesRequired; i++)
                        {
                            String tempTableTag = "QuotationItemTable_" + currentTable;

                            #region Additional Table
                            if (currentTable < NoOfPagesRequired && currentTable != NoOfPagesRequired)
                            {
                                SdtBlock lastElement = (SdtBlock)mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == tempTableTag).Single();
                                copyBlock = emptyElement;
                                copyBlock.SdtProperties.GetFirstChild<Tag>().Val = "QuotationItemTable_" + (currentTable + 1);

                                // Insert a blank new page
                                Run run = new Run(new Break() { Type = BreakValues.Page });
                                Paragraph para = new Paragraph(run);
                                SdtProperties sdtPr = new SdtProperties(new SdtAlias { Val = "NewPage" }, new Tag { Val = "NewPage" + currentTable });
                                SdtContentBlock sdtCBlock = new SdtContentBlock(para);
                                SdtBlock sdtBlock = new SdtBlock(sdtPr, sdtCBlock);
                                lastElement.InsertAfterSelf(sdtBlock);

                                sdtBlock.InsertAfterSelf(copyBlock);
                            }
                            #endregion

                            SdtBlock ccWithTable = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == tempTableTag).Single();
                            Table table = ccWithTable.Descendants<Table>().Single();
                            TableRow row = table.Elements<TableRow>().Last();
                            TableRow emptyRow = table.Elements<TableRow>().Last();
                            TableRow rowCopy = null;

                            int currentItemNo = 1;
                            decimal CarryForward = 0;

                            int SIndex = GetStartIndex(i);
                            int EIndex = GetEndIndex(quotItemList, currentTable, NoOfPagesRequired);
                            List<QuotationItemModel> tempList = GetRequiredItemModel(quotItemList, SIndex, EIndex);

                            #region Part a - Brought Forward
                            if (currentTable > 1)
                            {
                                TableCellProperties tcp1 = new TableCellProperties();
                                TableCellProperties tcp2 = new TableCellProperties();

                                row = table.Elements<TableRow>().Last();
                                rowCopy = (TableRow)row.Clone();
                                

                                String text = "Brought Forward :", text2 = BroughtForward.ToString("#,##0.00");
                                tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                    , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                                tcp2 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                    , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Single }, new TopBorder() { Val = BorderValues.Nil })));

                                row = table.Elements<TableRow>().Last();
                                row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                                GridSpan gs = new GridSpan { Val = 2 };
                                row.Descendants<TableCell>().ElementAt(4).Remove();
                                row.Descendants<TableCell>().ElementAt(4).Append(gs);
                                row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                                row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(5).Append(tcp2);
                                row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text2)));
                                row.Descendants<TableCell>().ElementAt(5).Append(rowTable);

                                table.AppendChild(rowCopy);
                                row = table.Elements<TableRow>().Last();
                            }
                            #endregion

                            #region Part b - Items
                            foreach (QuotationItemModel item in tempList)
                            {
                                // Copy the blank row
                                rowCopy = (TableRow)row.Clone();
                                tempStrn = (item.ItemNo == 0) ? "" : item.ItemNo.ToString();
                                row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                                row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.ItemDescription)));
                                row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.SORItem)));
                                row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                                tempStrn = (item.Qty == 0) ? "" : item.Qty.ToString();
                                row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                                row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.Unit)));
                                row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                tempStrn = (item.Rate == 0) ? "" : item.Rate.ToString("#,##0.00");
                                row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                                row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                                tempStrn = (item.ItemAmount == 0) ? "" : item.ItemAmount.ToString("#,##0.00");
                                TotalAmount += item.ItemAmount;
                                CarryForward += item.ItemAmount;
                                row.Descendants<TableCell>().ElementAt(6).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                                row.Descendants<TableCell>().ElementAt(6).Append(rowTable);

                                if (currentItemNo != tempList.Count)
                                    table.AppendChild(rowCopy);

                                row = table.Elements<TableRow>().Last();
                                currentItemNo++;
                            }
                            #endregion

                            #region Part c - Carry Forward
                            if(currentTable != NoOfPagesRequired && currentTable < NoOfPagesRequired)
                            {
                                rowCopy = (TableRow)emptyRow.Clone();
                                table.AppendChild(rowCopy);
                                row = table.Elements<TableRow>().Last();
                                row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(5).Append(rowTable);

                                TableCellProperties tcp1 = new TableCellProperties();
                                TableCellProperties tcp2 = new TableCellProperties();

                                row = table.Elements<TableRow>().Last();
                                rowCopy = (TableRow)row.Clone();
                                table.AppendChild(rowCopy);                                

                                String text = "Carry Forward :", text2 = CarryForward.ToString("#,##0.00");
                                tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                    , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                                tcp2 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                    , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Double }, new TopBorder() { Val = BorderValues.Single })));

                                row = table.Elements<TableRow>().Last();
                                row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                                GridSpan gs = new GridSpan { Val = 2 };
                                row.Descendants<TableCell>().ElementAt(4).Remove();
                                row.Descendants<TableCell>().ElementAt(4).Append(gs);
                                row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                                row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(5).Append(tcp2);
                                row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text2)));
                                row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                            }
                            #endregion

                            
                            if (currentTable == NoOfPagesRequired)
                            {
                                #region Part d - last two Rows
                                TableCellProperties tcp1 = new TableCellProperties();
                                TableCellProperties tcp2 = new TableCellProperties();

                                row = table.Elements<TableRow>().Last();
                                rowCopy = (TableRow)row.Clone();
                                table.AppendChild(rowCopy);

                                String text = "Total Amount :", text2 = TotalAmount.ToString("#,##0.00");
                                tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                    , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                                tcp2 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                    , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Double }, new TopBorder() { Val = BorderValues.Single })));

                                row = table.Elements<TableRow>().Last();
                                row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                                row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                                GridSpan gs = new GridSpan { Val = 2 };
                                row.Descendants<TableCell>().ElementAt(4).Remove();
                                row.Descendants<TableCell>().ElementAt(4).Append(gs);
                                row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                                row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                row.Descendants<TableCell>().ElementAt(5).Append(tcp2);
                                row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                        new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text2)));
                                row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                                #endregion

                                #region Part e - Remaining Lines if any
                                int NoOfRemainingLines = GetNoOfRemainingLines(quotItemList);

                                if (NoOfRemainingLines > 0)
                                {
                                    for (int k = 0; k < NoOfRemainingLines; k++)
                                    {
                                        row = table.Elements<TableRow>().Last();
                                        rowCopy = (TableRow)row.Clone();
                                        table.AppendChild(rowCopy);

                                        text = "";
                                        tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                        , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));

                                        row = table.Elements<TableRow>().Last();
                                        row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                                        row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                        row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                                        tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                        , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                                        row.Descendants<TableCell>().ElementAt(5).Append(tcp1);
                                        row.Descendants<TableCell>().ElementAt(5).GetFirstChild<Paragraph>().Remove();
                                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(text)));
                                        row.Descendants<TableCell>().ElementAt(5).Append(rowTable);
                                    }
                                }
                                #endregion
                            }
                            

                            currentTable++;
                            BroughtForward += CarryForward;
                        }
                    }
                    #endregion

                    #region Part III - Footer
                    String tWorkCompletionDate = "";

                    if (quotModel.WorkCompletionDate != null)
                        tWorkCompletionDate = Configuration.WorkCompletionDateWord + Configuration.Space + quotModel.WorkCompletionDate.Value.ToString("dd MMMM yyyy", CultureInfo.CreateSpecificCulture("en-US"));

                    if (quotModel.WorkCompletionDate <= DateTime.Today)
                        tWorkCompletionDate = "";

                    mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "WorkCompletionDate").Single().Descendants<Text>().First().Text = tWorkCompletionDate;
                    #endregion
                    #endregion
                }

                //#region PDF Conversion
                //String srcFilePath = destFilePath;
                //destFilePath = srcFilePath.Replace(".docx", ".pdf");

                //PDFUtil.WordToPDF(srcFilePath, destFilePath);
                //#endregion
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        private bool IsLessThanOrEqualTo9Items(List<QuotationItemModel> quotItemModelList)
        {
            bool isLessthan = false;

            if (quotItemModelList.Count <= 9)
                isLessthan = true;

            return isLessthan;
        }

        private int GetNoOfPages(List<QuotationItemModel> quotItemModelList)
        {
            double NoOfPages = (double)((double)quotItemModelList.Count / (double)16);
            return (int)Math.Ceiling(NoOfPages);
        }

        private int GetNoOfRemainingLines(List<QuotationItemModel> quotItemModelList)
        {
            int NoOFRemainingLines = Configuration.NoOfRowsForQuotation - (quotItemModelList.Count + 2);

            return NoOFRemainingLines;
        }

        private int GetStartIndex(int currentPageNo)
        {
            int resultIndex = currentPageNo * Configuration.MaxNoOfRecords;
            return resultIndex;
        }

        private int GetEndIndex(List<QuotationItemModel> quotItemModelList, int currPageNo, int noOfPage)
        {
            int resultIndex = (currPageNo * Configuration.MaxNoOfRecords) - 1;

            if (currPageNo == noOfPage)
                resultIndex = quotItemModelList.Count - 1;

            return resultIndex;
        }

        private List<QuotationItemModel> GetRequiredItemModel(List<QuotationItemModel> quotItemModelList, int SIndex, int EIndex)
        {
            List<QuotationItemModel> resultList = new List<QuotationItemModel>();

            for (int i = SIndex; i <= EIndex; i++)
                resultList.Add(quotItemModelList[i]);

            return resultList;
        }
    }
}